package com.xnyzc.lhy.didi.tongcheng.service.order.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.xnyzc.lhy.common.component.amap.GouldMapUtils;
import com.xnyzc.lhy.common.component.convert.DateToStringConverter;
import com.xnyzc.lhy.common.component.redis.RedisCommon;
import com.xnyzc.lhy.common.constant.MqConstant;
import com.xnyzc.lhy.common.constant.RedisPrefixConstant;
import com.xnyzc.lhy.common.entity.GouldResult;
import com.xnyzc.lhy.common.entity.Qw;
import com.xnyzc.lhy.common.entity.Rv;
import com.xnyzc.lhy.common.global.Configuration;
import com.xnyzc.lhy.common.penum.EErrorCode;
import com.xnyzc.lhy.common.penum.cms.EVehicleType;
import com.xnyzc.lhy.common.penum.comment.EOrderIsComment;
import com.xnyzc.lhy.common.penum.order.EOrderChannelType;
import com.xnyzc.lhy.common.penum.order.EOrderStatus;
import com.xnyzc.lhy.common.util.CheckUtil;
import com.xnyzc.lhy.common.util.DateUtil;
import com.xnyzc.lhy.common.util.IDUtil;
import com.xnyzc.lhy.common.util.LuckDrawUtil;
import com.xnyzc.lhy.didi.common.constants.EXieChengVehicleType;
import com.xnyzc.lhy.didi.config.AppPushConfig;
import com.xnyzc.lhy.didi.entity.billGroup.OaSysBillRuleGroup;
import com.xnyzc.lhy.didi.entity.invoice.TcInvoiceInfo;
import com.xnyzc.lhy.didi.entity.order.OaCOrderPersonal;
import com.xnyzc.lhy.didi.entity.param.other.OrderInfoCreated;
import com.xnyzc.lhy.didi.entity.param.other.StatisticalData;
import com.xnyzc.lhy.didi.entity.price.OaSysBillSpecialSceneRule;
import com.xnyzc.lhy.didi.entity.results.invoice.InvoiceResults;
import com.xnyzc.lhy.didi.mapper.order.OaCOrderPersonalMapper;
import com.xnyzc.lhy.didi.mapper.order.OaDBillMapper;
import com.xnyzc.lhy.didi.mapper.order.OaDOrderMapper;
import com.xnyzc.lhy.didi.mapper.other.OaDUserInfoMapper;
import com.xnyzc.lhy.didi.mapper.other.OaDUserMapper;
import com.xnyzc.lhy.didi.mapper.price.OaSysBillSpecialSceneRuleMapper;
import com.xnyzc.lhy.didi.mapper.price.OaSysPlatformTimeRuleMapper;
import com.xnyzc.lhy.didi.mapper.sys.OaSysOfficeMapper;
import com.xnyzc.lhy.didi.mapper.tongcheng.TcInvoiceMapper;
import com.xnyzc.lhy.didi.mq.MQProducer;
import com.xnyzc.lhy.didi.service.operation.CustomerServiceOperationService;
import com.xnyzc.lhy.didi.service.xiecheng.EmbargoAreaService;
import com.xnyzc.lhy.didi.service.xiecheng.XcPriceService;
import com.xnyzc.lhy.didi.tongcheng.entity.TongChengRv;
import com.xnyzc.lhy.didi.tongcheng.entity.param.order.*;
import com.xnyzc.lhy.didi.tongcheng.entity.results.*;
import com.xnyzc.lhy.didi.tongcheng.penum.ETongChengCallVehType;
import com.xnyzc.lhy.didi.tongcheng.penum.ETongChengErrorCode;
import com.xnyzc.lhy.didi.tongcheng.penum.ETongChengPriceType;
import com.xnyzc.lhy.didi.tongcheng.penum.ETongChengRideType;
import com.xnyzc.lhy.didi.tongcheng.service.order.TcOrderService;
import com.xnyzc.lhy.mis.entity.platform.OaSysPlatformTimeControl;
import com.xnyzc.lhy.mis.entity.system.*;
import com.xnyzc.lhy.order.entity.bill.OaDBill;
import com.xnyzc.lhy.order.entity.gps.OaDVehicleGps;
import com.xnyzc.lhy.order.entity.order.OaDOrder;
import com.xnyzc.lhy.order.entity.sidebar.OaSysOffice;
import com.xnyzc.lhy.order.entity.user.OaDUser;
import com.xnyzc.lhy.order.entity.user.OaDUserInfo;
import lombok.extern.slf4j.Slf4j;
import nuonuo.open.sdk.NNOpenSDK;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.Point;
import org.springframework.stereotype.Service;
import com.xnyzc.lhy.didi.mapper.billGroup.OaSysBillRuleGroupMapper;

import java.io.IOException;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Auther: lihao
 * @Date: 2020/7/5 18:04
 * @Description:
 */
@Service
@Slf4j
public class TcOrderServiceImpl implements TcOrderService {
    @Autowired
    private OaCOrderPersonalMapper oaCOrderPersonalMapper;
    @Autowired
    private OaDOrderMapper oaDOrderMapper;
    @Autowired
    private MQProducer producer;
    @Autowired
    private RedisCommon redisCommon;
    @Autowired
    private OaDUserInfoMapper userInfoMapper;
    @Autowired
    private OaDUserMapper oaDUserMapper;
    @Autowired
    private OaSysOfficeMapper oaSysOfficeMapper;
    @Autowired
    private OaDBillMapper oaDBillMapper;
    @Autowired
    private CustomerServiceOperationService customerServiceOperationService;
    @Autowired
    private TcInvoiceMapper tcInvoiceMapper;
    @Autowired
    private XcPriceService xcPriceService;
    @Autowired
    private OaSysPlatformTimeRuleMapper oaSysPlatformTimeRuleMapper;
    @Autowired
    private OaSysBillRuleGroupMapper oaSysBillRuleGroupMapper;
    @Autowired
    private OaSysBillSpecialSceneRuleMapper oaSysBillSpecialSceneRuleMapper;
    //    @Autowired
//    private OaSysUserSeparateAccountMapper oaSysUserSeparateAccountMapper;
    @Autowired
    private EmbargoAreaService embargoAreaService;

    private Integer channel = EOrderChannelType.tongcheng.getType();

    @Override
    public TongChengRv getTcOrderPrice(TcOrderPriceParam orderPriceParam) {
        log.info("同城查价入参：{}", JSON.toJSONString(orderPriceParam));
        long startTime = System.currentTimeMillis();
        //验证平台时间控制是否接单
        try {
            if (verificationTime(orderPriceParam)) {
                return TongChengRv.error(ETongChengErrorCode.city_null);
            }
        } catch (ParseException e) {
            log.info("验证平台时间 查价异常--->" + e.getMessage());
        }

        HashMap<Integer, Integer> staticalPriceMap = new HashMap<>();
        StatisticalData statisticalData = StatisticalData.builder()
                .channel(channel)
                .origin(orderPriceParam.getSname()).destination(orderPriceParam.getDname())
                .startLng(orderPriceParam.getSlon()).startLat(orderPriceParam.getSlat())
                .endLng(orderPriceParam.getDlon()).endLat(orderPriceParam.getDlat())
                .appointmentTime(orderPriceParam.getDeparture_time()*1000)
                .timestamp((long)orderPriceParam.getTimestamp()*1000)
                .build();

        GouldResult.RouteBean router = GouldMapUtils.getStrategy(orderPriceParam.getSlon() + "," + orderPriceParam.getSlat(), orderPriceParam.getDlon() + "," + orderPriceParam.getDlat());
        if (router == null) {
            return TongChengRv.error(ETongChengErrorCode.dataException);
        }

        String mRideType = orderPriceParam.getRide_type();
        if (CheckUtil.strIsEmpty(mRideType)) {
            return TongChengRv.error(ETongChengErrorCode.dataException);
        }
        String[] rideTypes = mRideType.split(",");

        TcOrderPriceResults results = new TcOrderPriceResults();
        List<TcPriceDetail> prices = new ArrayList<>();

        List<Integer> vehicleTypes = new ArrayList<>();
        for (String rideType : rideTypes) {
            vehicleTypes.add(ETongChengRideType.getByName(rideType).getValue());
        }

        int callType = ETongChengCallVehType.getByTcType(orderPriceParam.getService_id()).getType();
        Date startDate = new Date(orderPriceParam.getDeparture_time() * 1000L);

        String cityCode = orderPriceParam.getCity_code();
        // FIXME 删除手动转码 海口127-460100 上海321-310100
        if ("127".equals(cityCode)) {
            cityCode = "460100";
        }
        if ("321".equals(cityCode)) {
            cityCode = "310100";
        }
        String origin = orderPriceParam.getSname();
        String destination = orderPriceParam.getDname();

        statisticalData.setCallType(callType);
        statisticalData.setCityCode(cityCode);

        //判断起点、终点是否处在禁运区域
        HashMap<Object, Object> flagMap = verifyAreaCode(router, cityCode, callType, channel,origin,destination);//同程channel是2
        List<NewBillRules> newBillRules =(List<NewBillRules>)  flagMap.get("rules");
        String priceMarker = "";
        for (Integer vehicleType : vehicleTypes) {
            //判断禁运情况，如果命中禁运区域，直接进入下次循环
            if (flagMap.containsKey(vehicleType) && (Integer) flagMap.get(vehicleType) == 1) {//1说明命中
                continue;
            }
            RulesParam rulesParam=new RulesParam();
            NewBillRules billRules = newBillRules.get(0);
            List<RulesParam> fees = billRules.getFees();
            Integer drawRatio = billRules.getDrawRatio();
            Double premium = billRules.getPremium();
            for (int i = 0; i <fees.size() ; i++) {
                if (vehicleType==fees.get(i).getVehicleType().longValue()){
                    rulesParam=fees.get(i);
                    break;
                }
            }
            if (CheckUtil.objIsEmpty(rulesParam.getBillRules())){
                continue;
            }
            String ruleId=newBillRules.get(0).getRuleId().toString();
            Integer robable = newBillRules.get(0).getRobable();
            robable=robable==null?0:robable;
            // 返回值对象 --->预估价格计算
            EVehicleType mvehicleType = ETongChengRideType.getByType(vehicleType);
            if (mvehicleType == null) {
                continue;
            }
            HashMap<String, Object> priceMap = xcPriceService.getPriceDetail(channel, cityCode, mvehicleType, callType,
                    startDate, router, rulesParam,ruleId,robable,premium,drawRatio);
            if (priceMap == null) {
                long responseTime = System.currentTimeMillis()-startTime;
                statisticalData.setResponseTime(responseTime);
                //将orderPriceParam发送到mq中
                producer.sendMsg(statisticalData,MqConstant.DATA_PRICE_STATISTICAL,null,1);
                return TongChengRv.error(ETongChengErrorCode.dataException);
            }
            redisCommon.setHashMap(RedisPrefixConstant.DIDI_ESTIMATE + priceMap.get("estimateId").toString(), priceMap, Long.valueOf(86400));
            String estimateId = priceMap.get("estimateId").toString();
            BigDecimal distanceM = (BigDecimal) priceMap.get("distanceM");
            if(!vehicleTypes.get(vehicleTypes.size()-1).equals(vehicleType)){
                priceMarker += estimateId+",";
            }else{
                priceMarker += estimateId;
            }
            statisticalData.setMilage(distanceM.intValue());
            statisticalData.setPriceMarker(priceMarker);

            Double timeCount = (Double) priceMap.get("timeCount");
            BigDecimal totalFee = getFee(priceMap, "totalFee");//金额单位是元

            results.setDistance(distanceM.intValue());
            results.setEstimate_time(timeCount.intValue() * 60);

            TcPriceDetail price = new TcPriceDetail();
            price.setDynamic_rate(1D);
            price.setEstimate_id(estimateId);
            price.setEstimate_price(totalFee.multiply(new BigDecimal(100)).intValue());//金额单位转化为分
            price.setRide_type(ETongChengRideType.getById(vehicleType).name());
            price.setData_list(getFeeDetails(priceMap));//金额单位转化为分
            staticalPriceMap.put(vehicleType,totalFee.multiply(new BigDecimal(100)).intValue());
            prices.add(price);
        }

        results.setPrices(prices);
        String priceStr = JSON.toJSONString(staticalPriceMap);
        statisticalData.setPrices(priceStr);

        long responseTime = System.currentTimeMillis()-startTime;
        statisticalData.setResponseTime(responseTime);
        //将orderPriceParam发送到mq中
        producer.sendMsg(statisticalData,MqConstant.DATA_PRICE_STATISTICAL,null,1);
        //如果车型全部命中禁运区域，返回code为1，message为fail;
        if (CheckUtil.collectionIsEmpty(results.getPrices())) {
            return TongChengRv.error(ETongChengErrorCode.city_null);
        }
        log.info("同城询价结果：{}", results);
        return TongChengRv.wrap(results);
    }

    public HashMap verifyAreaCode(GouldResult.RouteBean router, String cityCode, int callType, int channel,String origin,String destination) {
        HashMap<Object, Object> reMap = new HashMap();
        //调用高德接口
        String sAdCode = router.getSAcode();
        String eAdCode = router.getEAcode();

        //  判断起点和终点是否包含数据库中的stationKeyword 返回该rulesNo
        Integer rulesNo = getRulesNo(origin,destination,cityCode,callType);
        //数据库或redis中查询禁行区设置,不区分运力类型
        List<NewBillRules> reMap1 = embargoAreaService.getPriceDetail(channel, cityCode, callType,rulesNo);
       // reMap1.get(0).getFees();
        List<RulesParam> fees=JSON.parseArray(reMap1.get(0).getJsonRules(),RulesParam.class);
        reMap1.get(0).setFees(fees);
        List<RulesParam> rulesParamList =fees;
        reMap.put("rules", reMap1);
        Iterator<RulesParam> rulesParamIterator = rulesParamList.iterator();
        while (rulesParamIterator.hasNext()) {
            RulesParam rulesParam= rulesParamIterator.next();
            List<OaSysBillRuleNewEmbargoMini> em=rulesParam.getRuleEmbargos();
            for (int i = 0; i < em.size(); i++) {
                OaSysBillRuleNewEmbargoMini embargoMini = em.get(i);
                int veTpe = ETongChengRideType.getById(rulesParam.getVehicleType()).getValue();
                //判断禁运起点和目的地勾选情况
                int refuseType = embargoMini.getRefuseType();
                int flag;
                if (refuseType == 0) {
                    //起点在其中则禁运
                    flag = 0;
                } else if (refuseType == 1 ) {
                    //终点禁运
                    flag = 1;
                } else if (refuseType == 2 ) {  //0 and 1终点禁运
                    // 终点或起点在其中
                    flag = 2;
                } else if (refuseType == 3 ) {
                    //起点和终点都在其中则禁运
                    flag = 3;
                }else if(refuseType == 4){
                    //无禁运
                    flag = 4;
                } else {
                    //默认无禁运
                    flag = 4;
                }
                int areaLevel = embargoMini.getAreaLevel();//地区等 省、市、县区
                boolean verifiedValue = verifyArea(embargoMini.getAreaCode(), sAdCode, eAdCode, areaLevel, flag);
                if (veTpe == 0) {//经济型
                    if (verifiedValue) {//如果判断为true，则说明命中禁运区域
                        reMap.put(veTpe, 1);
                        break;
                    } else {
                        reMap.put(veTpe, 0);
                    }
                } else if (veTpe == 1) {//舒适性
                    if (verifiedValue) {//如果判断为true，则说明命中禁运区域
                        reMap.put(veTpe, 1);
                        break;
                    } else {
                        reMap.put(veTpe, 0);
                    }
                } else if (veTpe == 2) {//商务型
                    if (verifiedValue) {//如果判断为true，则说明命中禁运区域
                        reMap.put(veTpe, 1);
                        break;
                    } else {
                        reMap.put(veTpe, 0);
                    }
                } else if (veTpe == 3) {//豪华型
                    if (verifiedValue) {//如果判断为true，则说明命中禁运区域
                        reMap.put(veTpe, 1);
                        break;
                    } else {
                        reMap.put(veTpe, 0);
                    }
                }

            }
        }
        return reMap;
    }

    /**
     * @param sAdCode   高德获取的起点adcode
     * @param eAdCode   高德获取的终点adcode
     * @param areaLevel 数据库保存的行政区划等级
     * @param flag      起点终点禁运情况
     * @return
     */
    public boolean verifyArea(String adcode, String sAdCode, String eAdCode, int areaLevel, int flag) {
        boolean r = false;
        if (flag == 4) { //不禁运直接返回
            return r;
        }
        String al = "";
        if (areaLevel == 0) {//省、直辖市
            //判断行政编吗前两位
            al = adcode.substring(0, 2);
            r = verifyAreaType(al, flag, sAdCode, eAdCode);
        } else if (areaLevel == 1) {//市级
            //市级判断前4位
            al = adcode.substring(0, 4);
            r = verifyAreaType(al, flag, sAdCode, eAdCode);
        } else if (areaLevel == 2) {//区县级
            //区县精确对比
            r = verifyAreaType(adcode, flag, sAdCode, eAdCode);
        }
        return r;
    }

    public boolean verifyAreaType(String al, int flag, String sAdCode, String eAdCode) {
        boolean r = false;
        if (flag == 0) {//起点是否在禁运区域
            r = sAdCode.startsWith(al);
        } else if (flag == 1) {//终点是否在禁运区域
            r = eAdCode.startsWith(al);
        } else if (flag == 2) {//起点或终点是否在禁运区域
            r = sAdCode.startsWith(al) || eAdCode.startsWith(al);
        }else if(flag == 3){//起点和终点是否在禁运区域
            r = sAdCode.startsWith(al) && eAdCode.startsWith(al);
        }
        return r;
    }


    /**
     * 查价验证平台时间控制是否接单
     *
     * @param orderPriceParam
     * @return
     */
    private Boolean verificationTimeByQPrice(TcOrderPriceParam orderPriceParam) throws ParseException {

        String cityCode = orderPriceParam.getCity_code();
        // FIXME 删除手动转码 海口127-460100 上海321-310100
        if ("127".equals(cityCode)) {
            cityCode = "460100";
        }
        if ("321".equals(cityCode)) {
            cityCode = "310100";
        }
        Date useDate = new Date(orderPriceParam.getDeparture_time() * 1000L);
        QueryWrapper<OaSysPlatformTimeControl> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(OaSysPlatformTimeControl.CHANNEL_ID, channel);
        queryWrapper.eq(OaSysPlatformTimeControl.CITY_ID, cityCode);
        queryWrapper.eq(OaSysPlatformTimeControl.DELETED, 0);

        List<OaSysPlatformTimeControl> platformTimeControlList = oaSysPlatformTimeRuleMapper.selectList(queryWrapper);

        if (CheckUtil.objIsEmpty(platformTimeControlList)) {
            return false;
        }
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
        //用车时间
        //Date useDate = new Date(orderPriceParam.getDeparture_time() * 1000L);
        Calendar useCalendar = Calendar.getInstance();
        useCalendar.setTime(useDate);
        //获取用车时间的号数
        int day = useCalendar.get(Calendar.DAY_OF_MONTH);

        //获取当前时间的号数
        Calendar curCalendar = Calendar.getInstance();
        curCalendar.setTime(new Date());
        int curDay = curCalendar.get(Calendar.DAY_OF_MONTH);

        //相差天数
        int differDay = day - curDay;
        if (differDay < 0) {//过时直接拒绝
            return true;
        }

        int useTime = differDay * 60 * 60 * 24 + useCalendar.get(Calendar.HOUR_OF_DAY) * 60 + useCalendar.get(Calendar.MINUTE);

        //请求时间
        Date timestamp = new Date(orderPriceParam.getTimestamp() * 1000L);
        Calendar timestampCalendar = Calendar.getInstance();
        timestampCalendar.setTime(timestamp);
        int timestampTime = timestampCalendar.get(Calendar.HOUR_OF_DAY) * 60 + timestampCalendar.get(Calendar.MINUTE);

        for (OaSysPlatformTimeControl info : platformTimeControlList) {
            if (info.getUseFullTime() == 0) {//使用全时就false-->优先判断
                return false;
            } else {
                //开始时间
                Calendar startTime = Calendar.getInstance();
                startTime.setTime(sdf.parse(info.getStartTime()));
                int start = startTime.get(Calendar.HOUR_OF_DAY) * 60 + startTime.get(Calendar.MINUTE);

                //结束时间
                Calendar endTime = Calendar.getInstance();
                endTime.setTime(sdf.parse(info.getEndTime()));
                int end = endTime.get(Calendar.HOUR_OF_DAY) * 60 + endTime.get(Calendar.MINUTE);

                //延长时间
                int delayTime = Integer.parseInt(info.getDelayTime());
                //判断方式为：开始时间≤请求提交时间 ≤结束时间 and 用车时间≤(结束时间（当日）+临近时间长度) == true，即拒绝服务
                if ((start <= timestampTime && timestampTime <= end) && useTime <= (end + delayTime)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 查价验证平台时间控制
     *
     * @param orderPriceParam
     * @return
     */
    private Boolean verificationTime(TcOrderPriceParam orderPriceParam) throws ParseException {

        String cityCode = orderPriceParam.getCity_code();
        // FIXME 删除手动转码 海口127-460100 上海321-310100
        if ("127".equals(cityCode)) {
            cityCode = "460100";
        }
        if ("321".equals(cityCode)) {
            cityCode = "310100";
        }
        //用车时间
        Date useDate = new Date(orderPriceParam.getDeparture_time() * 1000L);
        String currtDay = DateUtil.getStringDateShort(new Date()); //获取当前时间的yyyy-MM-dd年月日格式
        String useDay = DateUtil.convertToStringCustom(useDate,"yyyy-MM-dd HH:mm"); //获取用车时间的yyyy-MM-dd年月日格式

        //从redis查询
        String redisStr = redisCommon.getStr(RedisPrefixConstant.PLATFORM_TIME_RULE + channel + "_" + cityCode);
        OaSysPlatformTimeControl oaSysPlatformTimeControl = JSON.parseObject(redisStr, OaSysPlatformTimeControl.class);
        if (CheckUtil.objIsEmpty(oaSysPlatformTimeControl)) {
            //redis中查不到 查数据库
           /* OaSysPlatformTimeControl osp =  oaSysPlatformTimeRuleMapper.selectTimeByConditions(channel,cityCode,useDate,currtDay,useDay);
            if(CheckUtil.objIsNotEmpty(osp)){
                OaSysPlatformTimeControl newRule = new OaSysPlatformTimeControl();
                newRule.setControlId(IDUtil.nextId());
                newRule.setCityId(osp.getCityId());
                newRule.setChannelId(osp.getChannelId());
                newRule.setGroupId(osp.getGroupId());
                newRule.setCompanyId(osp.getCompanyId());
                newRule.setChannelName(osp.getChannelName());
                newRule.setUseFullTime(osp.getUseFullTime());
                newRule.setStartTime(osp.getStartTime());
                newRule.setEndTime(osp.getEndTime());
                newRule.setDelayTime(osp.getDelayTime());
                newRule.setCreateTime(osp.getCreateTime());
                newRule.setCreateUser(osp.getCreateUser());
                newRule.setUpdateUser(osp.getUpdateUser());
                newRule.setUpdateTime(osp.getUpdateTime());
                newRule.setDeleted(0);
                redisCommon.set(RedisPrefixConstant.PLATFORM_TIME_RULE+channel+"_"+cityCode,JSON.toJSONString(newRule));
                return true;
            }*/
            return false;
        }
        if(oaSysPlatformTimeControl.getUseFullTime() == 0 ){
            //使用全时就false-->优先判断
            return false;
        }
        long delayTime = Integer.parseInt(oaSysPlatformTimeControl.getDelayTime())*60*1000L;
        //组装当前日期年月日和限制的时分
        long currStartTime = DateUtil.convertStringToDate(currtDay+" "+oaSysPlatformTimeControl.getStartTime(),"yyyy-MM-dd HH:mm").getTime();
        long currEndTime = DateUtil.convertStringToDate(currtDay+" "+oaSysPlatformTimeControl.getEndTime(),"yyyy-MM-dd HH:mm").getTime();
        //预约用车时间
        long useTimestamp = useDate.getTime();
        // 限制的开始时间 <= 订单用车时间 <= 限制的结束时间 用车时间在限制时间范围内则返回true
        if(useTimestamp >= currStartTime && useTimestamp <= currEndTime+delayTime){
            return true;
        }
        return false;
    }

    /**
     * 创建价格验证平台时间控制是否接单
     *
     * @param param
     * @return
     */
    private Boolean verificationTimeByCPrice(TcCreateOrderParam param) throws ParseException {
        String cityCode = param.getCity_code();
        // FIXME 删除手动转码 海口127-460100 上海321-310100
        if ("127".equals(cityCode)) {
            cityCode = "460100";
        }
        if ("321".equals(cityCode)) {
            cityCode = "310100";
        }
        //用车时间
        Date useDate = new Date(param.getDeparture_time() * 1000L);
        String currtDay = DateUtil.getStringDateShort(new Date()); //获取当前时间的yyyy-MM-dd年月日格式
        String useDay = DateUtil.convertToStringCustom(useDate,"yyyy-MM-dd HH:mm"); //获取用车时间的yyyy-MM-dd年月日格式

        //从redis查询
        String redisStr = redisCommon.getStr(RedisPrefixConstant.PLATFORM_TIME_RULE + channel + "_" + cityCode);
        OaSysPlatformTimeControl oaSysPlatformTimeControl = JSON.parseObject(redisStr, OaSysPlatformTimeControl.class);
        if (CheckUtil.objIsEmpty(oaSysPlatformTimeControl)) {
            //redis中查不到 查数据库
           /* OaSysPlatformTimeControl osp =  oaSysPlatformTimeRuleMapper.selectTimeByConditions(channel,cityCode,useDate,currtDay,useDay);
            if(CheckUtil.objIsNotEmpty(osp)){
                OaSysPlatformTimeControl newRule = new OaSysPlatformTimeControl();
                newRule.setControlId(IDUtil.nextId());
                newRule.setCityId(osp.getCityId());
                newRule.setChannelId(osp.getChannelId());
                newRule.setGroupId(osp.getGroupId());
                newRule.setCompanyId(osp.getCompanyId());
                newRule.setChannelName(osp.getChannelName());
                newRule.setUseFullTime(osp.getUseFullTime());
                newRule.setStartTime(osp.getStartTime());
                newRule.setEndTime(osp.getEndTime());
                newRule.setDelayTime(osp.getDelayTime());
                newRule.setCreateTime(osp.getCreateTime());
                newRule.setCreateUser(osp.getCreateUser());
                newRule.setUpdateUser(osp.getUpdateUser());
                newRule.setUpdateTime(osp.getUpdateTime());
                newRule.setDeleted(0);
                redisCommon.set(RedisPrefixConstant.PLATFORM_TIME_RULE+channel+"_"+cityCode,JSON.toJSONString(newRule));
                return true;
            }*/
            return false;
        }
        if(oaSysPlatformTimeControl.getUseFullTime() == 0 ){
            //使用全时就false-->优先判断
            return false;
        }
        long delayTime = Integer.parseInt(oaSysPlatformTimeControl.getDelayTime())*60*1000L;
        //组装当前日期年月日和限制的时分
        long currStartTime = DateUtil.convertStringToDate(currtDay+" "+oaSysPlatformTimeControl.getStartTime(),"yyyy-MM-dd HH:mm").getTime();
        long currEndTime = DateUtil.convertStringToDate(currtDay+" "+oaSysPlatformTimeControl.getEndTime(),"yyyy-MM-dd HH:mm").getTime();
        //预约用车时间
        long useTimestamp = useDate.getTime();
        // 限制的开始时间 <= 订单用车时间 <= 限制的结束时间 用车时间在限制时间范围内则返回true
        if(useTimestamp >= currStartTime && useTimestamp <= currEndTime+delayTime){
            return true;
        }
        return false;
    }

    /**
     * 获取价格明细列表
     *
     * @return
     */
    private List<TcFeeDetail> getFeeDetails(HashMap<String, Object> priceMap) {
        BigDecimal startFee = getFee(priceMap, "startFee");
        BigDecimal mileageFee = getFee(priceMap, "mileageFee");
        BigDecimal otherFee = getFee(priceMap, "otherFee");
        BigDecimal tollsFee = getFee(priceMap, "tollsFee");
        BigDecimal permiumFee = getFee(priceMap, "permiumFee");

        BigDecimal percent = new BigDecimal(100);

        //价格明细列表
        List<TcFeeDetail> dataList = Lists.newArrayList();

        TcFeeDetail priceStartFee = new TcFeeDetail();
        priceStartFee.setAmount(startFee.multiply(percent).intValue());
        priceStartFee.setType(ETongChengPriceType.start_fee.name());
        priceStartFee.setDescription(ETongChengPriceType.start_fee.getDesc());

        TcFeeDetail priceKmFee = new TcFeeDetail();
        priceKmFee.setAmount(mileageFee.multiply(percent).intValue());
        priceKmFee.setType(ETongChengPriceType.normal_km_fee.name());
        priceKmFee.setDescription(ETongChengPriceType.normal_km_fee.getDesc());

        dataList.add(priceStartFee);
        dataList.add(priceKmFee);

        //高速路费-从高德地图返回中获取
        TcFeeDetail hightSpeedFree = new TcFeeDetail();
        hightSpeedFree.setAmount(tollsFee.multiply(percent).intValue());
        hightSpeedFree.setType(ETongChengPriceType.high_way_fee.name());
        hightSpeedFree.setDescription(ETongChengPriceType.high_way_fee.getDesc());
        dataList.add(hightSpeedFree);

        //保险费-同程中无保险费选项，故算在其他费用中
        otherFee = otherFee.add(permiumFee);
        TcFeeDetail otherFeeDetail = new TcFeeDetail();
        otherFeeDetail.setAmount(otherFee.multiply(percent).intValue());
        otherFeeDetail.setType(ETongChengPriceType.other_fee.name());
        otherFeeDetail.setDescription(ETongChengPriceType.other_fee.getDesc());

        dataList.add(otherFeeDetail);
        return dataList;
    }

    private BigDecimal getFee(HashMap<String, Object> map, String key) {
        Object object = map.get(key);
        if (object == null) {
            return new BigDecimal(0);
        }
        if (object instanceof BigDecimal) {
            return (BigDecimal) object;
        } else {
            return new BigDecimal(object.toString());
        }
    }

    @Override
    public TongChengRv getTcCreateOrderInfo(TcCreateOrderParam param) throws IOException {
        log.info("同城创建订单入参：{}", JSON.toJSONString(param));

        //验证平台时间控制是否接单
        try {
            if (verificationTimeByCPrice(param)) {
                return TongChengRv.error(ETongChengErrorCode.city_null);
            }
        } catch (ParseException e) {
            log.info("验证平台时间 创建订单异常 -->" + e.getMessage());
        }

        TcCreateOrderResults createOrderResults = new TcCreateOrderResults();
        //查询是否已经接单，已接单不接了
        String orderId = param.getOrder_id();
        OaCOrderPersonal personal = oaCOrderPersonalMapper.selectOne(Qw.create().eq(OaCOrderPersonal.ORDER_NO, orderId));
        if (personal != null) {
            createOrderResults.setOrder_id(orderId);
            createOrderResults.setSupplier_order_id(String.valueOf(personal.getPersonalId()));
            return TongChengRv.wrap(ETongChengErrorCode.success, createOrderResults);
        }
        String estimateKey = RedisPrefixConstant.DIDI_ESTIMATE + param.getEstimate_id();
        HashMap<String, Object> priceMap = redisCommon.getHashMap(estimateKey);
        if (priceMap == null) {
            return TongChengRv.error(ETongChengErrorCode.dataException);
        }
        Integer robable = (Integer) priceMap.get("robable");
        Long ruleId = Long.parseLong(priceMap.get("ruleId").toString());
        BigDecimal distanceKm = (BigDecimal) priceMap.get("distanceKm");
        BigDecimal timeCount = (BigDecimal) priceMap.get("timeCount");
        BigDecimal totalFee = getFee(priceMap, "totalFee");
        //抽成后的费用不用了
        BigDecimal drawFee = getFee(priceMap, "drawFee");
        BigDecimal startFee = getFee(priceMap, "startFee");
        BigDecimal mileageFee = getFee(priceMap, "mileageFee");
        if (ruleId == null) {
            return TongChengRv.error(ETongChengErrorCode.dataException);
        }

        Long personalId = IDUtil.nextId();

        String phone = param.getPassenger_mobile();
        int plength = phone.length();
        String phoneSuffix = phone.substring(plength - 4, plength);
        // 生成订单
        // FIXME 删除手动转码 海口127-460100 上海321-310100
        String cityCode = param.getCity_code();
        if ("127".equals(cityCode)) {
            cityCode = "460100";
        }
        if ("321".equals(cityCode)) {
            cityCode = "310100";
        }
        // TODO: 2021/3/25 根据配置随机分配订单给供应商。
        //oaSysOfficeMapper.getCompanyByAdCode(cityCode);
        Long officeId = getOfficeId(cityCode, ETongChengRideType.getByName(param.getRide_type()).getValue());
        //TODO 根据运力供应商配置的分成比例来计算价格
        //BigDecimal drawFee = getDrawFee(officeId, totalFee,cityCode);
        if (officeId == null || officeId < 1) {
            return TongChengRv.error(ETongChengErrorCode.dataException);
        }
        personal = new OaCOrderPersonal();
        personal.setDurationTime(timeCount);
        personal.setMilageDistance(distanceKm);
        personal.setTotalFee(totalFee);
        personal.setDrawFee(drawFee);
        personal.setStartFee(startFee);
        personal.setMileageFee(mileageFee);
        personal.setPersonalId(personalId);
        personal.setIsCarpool(0);
        personal.setRulesId(ruleId);
        personal.setOrderType(ETongChengCallVehType.getByTcType(param.getService_id()).getType());
        personal.setOrderStatus(EOrderStatus.waitingResponse.getType());
        personal.setPassengerName(param.getPassenger_name());
        personal.setPassengerPhone(phone);
        personal.setPassengerPhoneSuffix(phoneSuffix);
        personal.setOrderChannel(channel);
        //personal.setOrderType(ECallVehType.reservation.getType());
        personal.setAppointment(new Date(param.getDeparture_time() * 1000));
        personal.setCityId(cityCode);
        //数据类型不一样，做映射处理
        personal.setVehicleType(ETongChengRideType.getByName(param.getRide_type()).getValue());
        personal.setOrderNo(orderId);
        personal.setCreateTime(new Date());
        personal.setCreateUser(param.getPassenger_name());
        personal.setUpdateTime(new Date());
        personal.setUpdateUser(param.getPassenger_name());
        //位置信息
        personal.setStartLat(String.valueOf(param.getSlat()));
        personal.setStartLng(String.valueOf(param.getSlon()));
        personal.setEndLng(String.valueOf(param.getDlon()));
        personal.setEndLat(String.valueOf(param.getDlat()));
        personal.setStartAddress(param.getSname());
        personal.setEndAddress(param.getDname());
        personal.setFlightDate(param.getFlight_date());
        personal.setFlightDelayTime(param.getFlight_delay_time());
        personal.setFlightNo(param.getFlight_no());
        //预估价一口价标识
        personal.setChargeType(param.getCharge_type());
        personal.setEstimateId(Long.valueOf(param.getEstimate_id()));
        //添加订单到所在地公司下
        personal.setOfficeId(officeId);
        int insert = oaCOrderPersonalMapper.insert(personal);
        if (insert > 0) {
            try {
                //app推送信息
                String appPushResult = AppPushConfig.AppPush(orderId);
                log.info("app推送结果---->" + appPushResult);
                System.out.println("appPushResult --->" + appPushResult);
            } catch (Exception e) {
                log.info("app推送异常---->" + e.getMessage());
            }
            producer.sendMsg(personal, MqConstant.BIND_DEFAULT_DRIVER, null, 1);
            producer.sendMsg(personal,MqConstant.NEW_ORDER_TO_MANAGER,null,1);
            OrderInfoCreated orderInfoCreated = OrderInfoCreated.builder().priceMarker(param.getEstimate_id())
                    .vehicleType(ETongChengRideType.getByName(param.getRide_type()).getValue())
                    .timestamp((long)param.getTimestamp()*1000).build();
            producer.sendMsg(orderInfoCreated,MqConstant.ORDER_INFO_CREATED,null,1);
            if (robable == 1) {
                //发送新订单通知
                producer.sendMsg(personal, MqConstant.NOTICE_NEW_ORDER, null, 1);
                //抢单时间为行程开始前两个小时
                long endTime = personal.getAppointment().getTime() - Configuration.DELAY_ROB_BOOKING;
                String bookingKey = RedisPrefixConstant.ORDER_BOOKING + personal.getOfficeId() + ":" + orderId;
                redisCommon.set(bookingKey, JSON.toJSONString(personal));
                redisCommon.addToZSet(RedisPrefixConstant.ORDER_TC_HALL+personal.getCityId(), bookingKey, endTime);
            }
            createOrderResults.setOrder_id(orderId);
            createOrderResults.setSupplier_order_id(String.valueOf(personalId));
            return TongChengRv.wrap(ETongChengErrorCode.success, createOrderResults);
        } else {
            return TongChengRv.wrap(ETongChengErrorCode.dataException);
        }
    }

    /**
     * @param cityCode 城市编码
     * @param rideType express(0, "经济型"),
     *                 compact(1, "舒适性"),
     *                 premium(2, "商务型"),
     *                 luxury(3, "豪华型");
     * @return
     */
    public Long getOfficeId(String cityCode, Integer rideType) {
        Long officeId = 0L;
        List<OaSysOffice> companysByAdCode = oaSysOfficeMapper.getCompanysByAdCode(cityCode);
        if (CheckUtil.collectionIsEmpty(companysByAdCode)) {
            return null;
        }
        if (companysByAdCode.size() == 1) {//如果只有一个运力，直接返回
            return companysByAdCode.get(0).getOfficeId();
        }
        Map<String, Integer> drawMap = new HashMap<>(16);
        for (Iterator<OaSysOffice> oaSysOfficeIterator = companysByAdCode.iterator(); oaSysOfficeIterator.hasNext(); ) {
            OaSysOffice office = oaSysOfficeIterator.next();
            if (CheckUtil.strIsEmpty(office.getExpand1())) {
                continue;
            }
            String[] split = office.getExpand1().split(",")[rideType].split(":");
            String k = office.getOfficeId().toString();
            int v = Integer.valueOf(split[1]);
            drawMap.put(k, v);
        }
        if (CheckUtil.mapIsEmpty(drawMap)) {
            officeId = companysByAdCode.get(0).getOfficeId();
        } else {
            officeId = Long.parseLong(LuckDrawUtil.weightRandom(drawMap));
        }
        return officeId;
    }

    /**
     * 根据公司officeId去查询运力提供商的分成比例进行计算
     *
     * @param officeId
     * @param totalFee
     * @return
     */
    public BigDecimal getDrawFee(Long officeId, BigDecimal totalFee,String adCode) {
        BigDecimal drawFee = new BigDecimal(0);
        BigDecimal percent = new BigDecimal(100);
        QueryWrapper<OaSysBillRuleGroup> wrapper = new QueryWrapper<>();
        wrapper.eq(OaSysBillRuleGroup.COMPANY_ID, officeId);
        wrapper.eq(OaSysBillRuleGroup.CITY_ID,adCode);
        OaSysBillRuleGroup billGroup = oaSysBillRuleGroupMapper.selectOne(wrapper);
        drawFee = totalFee.subtract(totalFee.multiply(new BigDecimal(billGroup.getDrawRatio())).
                divide(percent, 2, RoundingMode.HALF_UP));
        return drawFee;
    }

    @Override
    public TongChengRv cancelOrder(TcCancelOrderParam param) {
        log.info("同城取消订单入参：{}", JSON.toJSONString(param));
        //通过PersonalId查找OaCOrderPersonal，并将订单状态置为取消
        OaCOrderPersonal personal = oaCOrderPersonalMapper.selectOne(Qw.create().eq(OaCOrderPersonal.PERSONAL_ID, param.getOrder_id()));
        if (personal == null) {
            return TongChengRv.wrap(ETongChengErrorCode.dataException);
        }

        int status = personal.getOrderStatus();

        personal.setOrderStatus(EOrderStatus.cancelOrderNoNeedPayment.getType());
        //添加乘客取消订单时间
        personal.setCancelOrderTime(new Date());
        TcCancelOrderResults results = new TcCancelOrderResults();
        results.setOrder_id(personal.getOrderNo());
        if (oaCOrderPersonalMapper.updateById(personal) > 0) {
            //更新司机订单状态-->司机已接单需要更新
            if (personal.getDriverId() != null) {//确保乘客订单已指派司机
                QueryWrapper<OaDOrder> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq(OaDOrder.DRIVER_ID, personal.getDriverId());
                queryWrapper.eq(OaDOrder.ORDER_NO, personal.getOrderNo());
                List<OaDOrder> oaDOrderList = oaDOrderMapper.selectList(queryWrapper);
                for (OaDOrder info : oaDOrderList) {
                    info.setOrderStatus(EOrderStatus.cancelOrderNoNeedPayment.getType());
                    oaDOrderMapper.updateById(info);
                }
            }
            //删除延时任务所需数据
            String bookingKey = RedisPrefixConstant.ORDER_BOOKING + personal.getOfficeId() + ":" + personal.getOrderNo();
            redisCommon.remove(bookingKey);
            redisCommon.delFromZSet(RedisPrefixConstant.ORDER_TC_HALL+personal.getCityId(), bookingKey);
            redisCommon.delFromZSet(RedisPrefixConstant.ORDER_TC_ZSET2, bookingKey);
            redisCommon.delFromZSet(RedisPrefixConstant.ORDER_TC_ZSET3, bookingKey);
            redisCommon.delFromZSet(RedisPrefixConstant.ORDER_TC_ZSET4, bookingKey);
            redisCommon.delFromZSet(RedisPrefixConstant.ORDER_TC_ZSET5, bookingKey);

            //删除rediskey
            String key = RedisPrefixConstant.ORDER_OA_D_ORDER + personal.getOrderNo();
            if (redisCommon.hashKey(key)) {
                if (CheckUtil.objIsNotEmpty(personal.getDriverId())) {
                    redisCommon.remove(RedisPrefixConstant.ORDER_VEH + personal.getDriverId());
                }
                if (CheckUtil.objIsNotEmpty(personal.getUserId())) {
                    redisCommon.remove(RedisPrefixConstant.ORDER_USER + personal.getUserId());
                }
                redisCommon.remove(key);
            }

            results.setIs_canceled(1);
            String estimateKey = RedisPrefixConstant.DIDI_ESTIMATE + personal.getEstimateId();
            HashMap<String, Object> priceMap = redisCommon.getHashMap(estimateKey);
            long current = System.currentTimeMillis();
            if (current > (personal.getAppointment().getTime() - 1 * 60 * 60 * 1000L)) {
                //距离预约时间小于1小时取消订单
                results.setNeed_pay(1);
                BigDecimal totalFee = getFee(priceMap, "totalFee");
                results.setCost(totalFee.intValue());
                EOrderStatus orderStatus = EOrderStatus.findById(status);
                switch (orderStatus) {
                    case driverOrder: {
                        //无补偿
                    }
                    break;
                    case reservationLocation: {
                        //司机已出发则补偿15%，最大值15，20，25
                        BigDecimal fee = personal.getDrawFee().multiply(new BigDecimal(0.15));
                        fee = fee.setScale(2, BigDecimal.ROUND_HALF_UP);
                        EVehicleType vehicleType = EVehicleType.findVehType(personal.getVehicleType());
                        switch (vehicleType) {
                            case vehTypeEconomic: {
                                if (fee.doubleValue() > 15) {
                                    fee = new BigDecimal(15);
                                }
                            }
                            break;
                            case vehTypeComfortable: {
                                if (fee.doubleValue() > 20) {
                                    fee = new BigDecimal(20);
                                }
                            }
                            break;
                            case vehTypeBusiness:
                            case vehTypeLuxury: {
                                if (fee.doubleValue() > 25) {
                                    fee = new BigDecimal(25);
                                }
                            }
                            break;
                        }
                        //customerServiceOperationService.saveOaDBill(personal.getOrderNo(), fee, personal.getDriverId());
                    }
                    break;
                    case driverArrived: {
                        //司机到达则补偿30%，最大值30，40，50
                        BigDecimal fee = personal.getDrawFee().multiply(new BigDecimal(0.3));
                        fee = fee.setScale(2, BigDecimal.ROUND_HALF_UP);
                        EVehicleType vehicleType = EVehicleType.findVehType(personal.getVehicleType());
                        switch (vehicleType) {
                            case vehTypeEconomic: {
                                if (fee.doubleValue() > 30) {
                                    fee = new BigDecimal(30);
                                }
                            }
                            break;
                            case vehTypeComfortable: {
                                if (fee.doubleValue() > 40) {
                                    fee = new BigDecimal(40);
                                }
                            }
                            break;
                            case vehTypeBusiness:
                            case vehTypeLuxury: {
                                if (fee.doubleValue() > 50) {
                                    fee = new BigDecimal(50);
                                }
                            }
                            break;
                        }
                        //customerServiceOperationService.saveOaDBill(personal.getOrderNo(), fee, personal.getDriverId());
                    }
                    break;
                    default: {
                        log.info("取消订单其他状态-" + orderStatus.getValue());
                    }
                }
            } else {
                results.setNeed_pay(0);
            }
            return TongChengRv.wrap(results);
        } else {
            return TongChengRv.wrap(ETongChengErrorCode.dataException);
        }
    }

    @Override
    public TongChengRv getDriverLocation(TcDriverLocationParam param) {
        log.info("同城获取司机位置入参：{}", JSON.toJSONString(param));
        OaCOrderPersonal personal = oaCOrderPersonalMapper.selectOne(Qw.create().eq(OaCOrderPersonal.PERSONAL_ID, param.getOrder_id()));
        if (personal == null) {
            return TongChengRv.wrap(ETongChengErrorCode.clientId_err);
        }

        String redisKey = RedisPrefixConstant.GPS_VEH_KEY_PREFIX + personal.getDriverId();
        //log.info("同城获取司机位置redisKey:" + redisKey);
        String string = redisCommon.getStr(redisKey);
        //log.info("同城获取司机位置data:" + string);
        if (string == null) {
            return TongChengRv.error(ETongChengErrorCode.driverInfoIsNull);
        } else {
            OaDVehicleGps oaDVehicleGps = JSON.parseObject(string, OaDVehicleGps.class);

            TcDriverLocationResults results = new TcDriverLocationResults();
            BigDecimal mlng = new BigDecimal(oaDVehicleGps.getLng());
            BigDecimal mlat = new BigDecimal(oaDVehicleGps.getLat());
            Double lon = mlng.setScale(6, BigDecimal.ROUND_HALF_UP).doubleValue();
            Double lat = mlat.setScale(6, BigDecimal.ROUND_HALF_UP).doubleValue();
            results.setLon(lon);
            results.setLat(lat);
            return TongChengRv.wrap(results);
        }
    }

    @Override
    public TongChengRv getOrderInfo(TcOrderInfoParam param) {
        log.info("同城获取订单详情入参：{}", JSON.toJSONString(param));
        OaCOrderPersonal personal = oaCOrderPersonalMapper.selectOne(Qw.create().eq(OaCOrderPersonal.PERSONAL_ID, param.getOrder_id()));
        if (personal == null) {
            return TongChengRv.error(ETongChengErrorCode.orderid_null);
        }

        DateToStringConverter converter = new DateToStringConverter();

        TcOrderInfoResults results = new TcOrderInfoResults();
        results.setOrder_id(personal.getOrderNo());
        results.setIsEvaluated(EOrderIsComment.yes.getValue() == personal.getIsComment());
        results.setDeparture_time(converter.convert(personal.getCreateTime()));
        //results.setStatus(personal.getOrderStatus());
        results.setRide_type(ETongChengRideType.getById(personal.getVehicleType()).name());

        TcPassenger passenger = new TcPassenger();
        passenger.setMobile(personal.getPassengerPhone());
        passenger.setName(personal.getPassengerName());
        results.setPassenger(passenger);

        TcOrigin startPos = new TcOrigin();
        startPos.setName(personal.getStartAddress());
        startPos.setLat(Float.parseFloat(personal.getStartLat()));
        startPos.setLon(Float.parseFloat(personal.getStartLng()));
        results.setOrigin(startPos);

        TcOrigin endPos = new TcOrigin();
        endPos.setName(personal.getEndAddress());
        endPos.setLat(Float.parseFloat(personal.getEndLat()));
        endPos.setLon(Float.parseFloat(personal.getEndLng()));
        results.setDestination(endPos);

        Long driverId = personal.getDriverId();
        if (driverId != null) {
            OaDUser oaDUser = oaDUserMapper.selectOne(Qw.create().eq(OaDUser.DRIVER_ID, driverId));
            if (oaDUser != null) {
                TcDriver driver = new TcDriver();
                driver.setId(String.valueOf(oaDUser.getDriverId()));
                driver.setName(oaDUser.getDriverName());
                driver.setMobile(oaDUser.getDriverPhone());
                driver.setLevel(4.9);
                results.setDriver(driver);
//            driver.setLevel(driverInfo.getTotalServiceScore() / 20.0);
            }
        }

        OaDBill bill = oaDBillMapper.selectOne(Qw.create().eq(OaDBill.ORDER_NUMBER, personal.getOrderNo()));
        if (bill != null) {
            String estimateKey = RedisPrefixConstant.DIDI_ESTIMATE + personal.getEstimateId();
            HashMap<String, Object> priceMap = redisCommon.getHashMap(estimateKey);
            if (priceMap != null) {
                TcCast cast = new TcCast();
                cast.setAmount((int) (bill.getBillAmount().doubleValue() * 100));
                cast.setDistance(personal.getMilageDistance().intValue());
                cast.setDuration(personal.getDurationTime().intValue());

                cast.setDetail(getFeeDetails(priceMap));
                results.setCost(cast);
            }
        }

        return TongChengRv.wrap(results);
    }

    @Override
    public TongChengRv orderPaySync(TcOrderPayStatusParam param) {
        log.info("同城同步支付详情入参：{}", JSON.toJSONString(param));
        //乘客订单
        OaCOrderPersonal personal = oaCOrderPersonalMapper.selectOne(Qw.create().eq(OaCOrderPersonal.PERSONAL_ID, param.getOrder_id()));
        if (personal == null) {
            return TongChengRv.error(ETongChengErrorCode.orderid_null);
        }
        QueryWrapper<OaDOrder> oaDOrderQueryWrapper = new QueryWrapper<>();
        oaDOrderQueryWrapper.eq(OaDOrder.ORDER_NO, personal.getOrderNo());
        //司机订单
        OaDOrder oaDOrder = oaDOrderMapper.selectOne(oaDOrderQueryWrapper);
        Integer status = param.getStatus();
        if (status != null && status != 1) {
            personal.setOrderStatus(EOrderStatus.sendBill.getType());
            if (oaDOrder != null) {//确保司机订单不是空
                oaDOrder.setOrderStatus(EOrderStatus.sendBill.getType());
            }
        } else {
            personal.setOrderStatus(EOrderStatus.paymented.getType());
            if (oaDOrder != null) {//确保司机订单不是空
                oaDOrder.setOrderStatus(EOrderStatus.paymented.getType());
            }
        }
        oaCOrderPersonalMapper.updateById(personal);
        if (oaDOrder != null) {//确保司机订单不是空
            oaDOrderMapper.updateById(oaDOrder);
        }
        JSONObject json = new JSONObject();
        json.put("order_id", personal.getOrderNo());
        return TongChengRv.wrap(json);
    }

    @Override
    public TongChengRv getAccountInfo(TcAccountInfoParam param) {
        log.info("同城获取账单详情入参：{}", JSON.toJSONString(param));
        OaCOrderPersonal personal = oaCOrderPersonalMapper.selectOne(Qw.create().eq(OaCOrderPersonal.PERSONAL_ID, param.getOrder_id()));
        if (personal == null) {
            return TongChengRv.error(ETongChengErrorCode.orderid_null);
        }
        TcFeeDetailResults results = new TcFeeDetailResults();
        results.setOrder_id(personal.getOrderNo());
        results.setCreate_time(personal.getCreateTime().getTime() / 1000);

        Integer status = personal.getOrderStatus();
        if (status != null && status == EOrderStatus.paymented.getTypeInt()) {
            results.setOrder_completed(1);
            results.setAmount((int) (personal.getTotalFee().doubleValue() * 100));

            String estimateKey = RedisPrefixConstant.DIDI_ESTIMATE + personal.getEstimateId();
            HashMap<String, Object> priceMap = redisCommon.getHashMap(estimateKey);
            if (priceMap != null) {
                results.setDetail(getFeeDetails(priceMap));
            }
        } else {
            results.setOrder_completed(0);
        }
        return TongChengRv.wrap(results);
    }

    @Override
    public TongChengRv getInvoice(TcInvoiceParam param) {
        log.info("同城申请发票入参：{}", JSON.toJSONString(param));
        if (param.getOrder_id() == null) {
            return TongChengRv.error(ETongChengErrorCode.orderid_null);
        }
        //查看乘客订单是否存在
        OaCOrderPersonal personal = oaCOrderPersonalMapper.selectOne(Qw.create().eq(OaCOrderPersonal.PERSONAL_ID, param.getOrder_id()));
        if (personal == null) {
            return TongChengRv.error(ETongChengErrorCode.orderis_null);
        }
        //查看是否已开发票
        TcInvoiceInfo info = tcInvoiceMapper.selectOne(Qw.create().eq(TcInvoiceInfo.ORDER_ID, param.getOrder_id()));
        if (info != null) {
            return TongChengRv.error(ETongChengErrorCode.order_repeat);
        }
        //获取诺诺令牌
        TcInvoiceInfo info2 = tcInvoiceMapper.selectById(1);
        if (info2 == null) {
            info2.setId(1L);
            tcInvoiceMapper.insert(info2);
        }
        //自定义特定时间--->2020-12-31 23:59:59
        long times = 1609430399000L;
        //发票的序列号
        String invoiceSerialNum = null;
        //需要注意乘客预约时间可能为空
//        if(CheckUtil.objIsNotEmpty(personal.getAppointment()) && personal.getAppointment().getTime() > times){
//            //申请诺诺平台开票的 发票的序列号 -->收税发票
//            invoiceSerialNum = getNuoNuoInvoice(param,info2);
//        }else if(CheckUtil.objIsNotEmpty(personal.getAppointment()) && personal.getAppointment().getTime() <= times){
//            //申请诺诺平台开票的 发票的序列号 -->免税发票
        invoiceSerialNum = getNuoNuoInvoice2(param, info2);
//        }
        if (invoiceSerialNum == null) {
            return TongChengRv.error(ETongChengErrorCode.invoiceid_is_access);
        }
        info = new TcInvoiceInfo();
        info.setId(IDUtil.nextId());
        info.setClientId(param.getClientId());
        info.setOrderId(param.getOrder_id());
        info.setTitle(param.getTitle());
        info.setAmount(param.getAmount().divide(BigDecimal.valueOf(100), 2, BigDecimal.ROUND_HALF_DOWN));
        info.setBuyerType(param.getBuyer_type());
        info.setTaxNumber(param.getTax_number());
        info.setReceiveName(param.getReceive_name());
        info.setReceiveMobile(param.getReceive_mobile());
        info.setReceiveEmail(param.getReceive_email());
        info.setInvoiceType(param.getInvoice_type());
        info.setRegistAddress(param.getRegist_address());
        info.setRegistPhone(param.getRegist_phone());
        info.setOpenBank(param.getOpen_bank());
        info.setBankAccount(param.getBank_account());
        info.setInvoiceRemark(param.getInvoice_remark());
        info.setInvoiceStatus(1);//待开票状态
        info.setInvoiceUrl(null);
        info.setDepartmentId(2);
        info.setTimesTamp(new Date(param.getTimestamp() * 1000L));
        info.setInvoiceSerialNum(invoiceSerialNum);//发票的序列号-->可以查看发票的pdf的url凭证
        info.setDeleted(0);
        //保存发票信息
        tcInvoiceMapper.insert(info);

        //返回信息
        InvoiceResults results = new InvoiceResults();
        results.setInvoice_id(info.getId());
        results.setAmount(info.getAmount());
        results.setApplication_time(param.getTimestamp());
        results.setReceive_name(info.getReceiveName());
        results.setReceive_email(info.getReceiveEmail());
        results.setReceive_mobile(info.getReceiveMobile());
        results.setInvoice_type(info.getInvoiceType());
        results.setInvoice_url(info.getInvoiceUrl());
        results.setTitle(info.getTitle());
        results.setStatus(info.getInvoiceStatus());

        return TongChengRv.wrap2(results);
    }

    /***
     *   申请诺诺平台发票--->收税0.03
     * @param param
     * @return
     */
    public String getNuoNuoInvoice(TcInvoiceParam param, TcInvoiceInfo info) {

        String buyerName = null;
        if (param.getBuyer_type() == 1) {
            buyerName = "个人";
        } else {
            buyerName = "单位";
        }
        Date date = new Date(param.getTimestamp() * 1000L);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式

        NNOpenSDK sdk = NNOpenSDK.getIntance();
        String taxnum = "91510107749745776R"; // 授权企业税号
        String appKey = "97771535";
        String appSecret = "4A3C10287D414583";
        String method = "nuonuo.ElectronInvoice.requestBillingNew"; // API方法名
        String token = info.getAccessToken();
        if (token == null) {
            //自用型应用获取令牌
            String json = NNOpenSDK.getIntance().getMerchantToken(appKey, appSecret);
            System.out.println("json" + json);
            org.json.JSONObject jSONObject = new org.json.JSONObject(json);
            token = jSONObject.get("access_token").toString();
            info.setAccessToken(token);
            tcInvoiceMapper.updateById(info);
        }
        BigDecimal amount = param.getAmount().divide(BigDecimal.valueOf(100), 2, BigDecimal.ROUND_HALF_DOWN);
        String address = param.getRegist_address();
        if (address == null) {
            address = "";
        }
        String bankAccount = param.getBank_account();
        if (bankAccount == null) {
            bankAccount = "";
        }
        String content = "{" +
                "\"order\": {" +
                "\"terminalNumber\": \"\"," +
                "\"invoiceDetail\": [ " +
                "{" +
                "\"specType\": \"\"," +
                "\"taxExcludedAmount\": \"" + amount.subtract(amount.multiply(BigDecimal.valueOf(0.03))) + "\"," +
                "\"invoiceLineProperty\": \"0\"," +
                "\"favouredPolicyName\": \"\"," +
                "\"num\": \"\"," +
                "\"withTaxFlag\": \"1\"," +
                "\"tax\": \"" + amount.multiply(BigDecimal.valueOf(0.03)) + "\"," +
                "\"favouredPolicyFlag\": \"0\"," +
                "\"taxRate\": \"0.03\"," + //发票税率
                "\"unit\": \"\"," +
                "\"deduction\": \"0\"," +
                "\"price\": \"\"," +
                "\"zeroRateFlag\": \"\"," +
                "\"goodsCode\": \"\"," +
                "\"selfCode\": \"\"," +
                "\"goodsName\": \"客运服务费\"," +
                "\"taxIncludedAmount\": \"" + amount + "\" " +
                "}" +
                "]," +
                "\"buyerTel\": \"" + param.getReceive_mobile() + "\"," +
                "\"listFlag\": \"0\"," + //清单标志：非清单:0；清单:1，默认:0
                "\"pushMode\": \"2\"," +
                "\"departmentId\": \"9F7E9439CA8B4C60A2FFF3EA3290B088\"," +
                "\"clerkId\": \"e8dd73c6afd24df49b407906bcfcd468\"," +//开票员ID
                "\"remark\": \"" + param.getInvoice_remark() + "\"," +
                "\"checker\": \"杜莉\"," +
                "\"payee\": \"杜莉\"," + //收款人
                "\"buyerAddress\": \"" + address + "\"," +
                "\"buyerTaxNum\": \"" + param.getTax_number() + "\"," +
                "\"invoiceType\": \"1\"," +
                "\"invoiceLine\": \"p\"," +
                "\"email\": \"" + param.getReceive_email() + "\"," +
                "\"salerAccount\": \"" + "7411910182600026305" + "中信银行股份有限公司成都红星路支行" + "\"," +
                "\"salerTel\": \"028-68881888\"," +
                "\"orderNo\": \"" + param.getOrder_id() + "\"," +
                //"\"callBackUrl\": \"http:127.0.0.1/invoice/callback/\"," +
                "\"buyerName\": \"" + param.getTitle() + "\"," +
                "\"invoiceDate\": \"" + sdf.format(date) + "\"," +
                "\"invoiceCode\": \"\"," +
                "\"invoiceNum\": \"\"," +
                "\"salerAddress\": \"成都市武侯区七里路499号1栋3层302号\"," +
                "\"clerk\": \"张玲\"," + //开票员
                "\"buyerPhone\": \"" + param.getReceive_mobile() + "\"," +
                "\"buyerAccount\": \"" + bankAccount + "\"," +
                "\"productOilFlag\": \"0\"," +
                "\"extensionNumber\": \"\"," +
                "\"salerTaxNum\": \"" + taxnum + "\"," +
                "\"listName\": \"详见销货清单\"," +
                "\"proxyInvoiceFlag\": \"0\" " +
                "} " +
                "}";

        String url = "https://sdk.nuonuo.com/open/v1/services"; // SDK请求地址
        String senid = UUID.randomUUID().toString().replace("-", ""); // 唯一标识，32位随机码，无需修改，保持默认即可
        String result = sdk.sendPostSyncRequest(url, senid, appKey, appSecret, token, taxnum, method, content);
        System.out.println(result);
        try {
            //转换获取发票序列号
            org.json.JSONObject jSONObject2 = new org.json.JSONObject(result);
            String result2 = jSONObject2.get("result").toString();
            org.json.JSONObject jSONObject3 = new org.json.JSONObject(result2);
            String invoiceSerialNum = jSONObject3.get("invoiceSerialNum").toString();
            return invoiceSerialNum;
        } catch (Exception e) {
            return null;
        }
    }

    /***
     *   申请诺诺平台发票--->免税
     * @param param
     * @return
     */
    public String getNuoNuoInvoice2(TcInvoiceParam param, TcInvoiceInfo info) {

        String buyerName = null;
        if (param.getBuyer_type() == 1) {
            buyerName = "个人";
        } else {
            buyerName = "单位";
        }
        Date date = new Date(param.getTimestamp() * 1000L);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式

        NNOpenSDK sdk = NNOpenSDK.getIntance();
        String taxnum = "91510107749745776R"; // 授权企业税号
        String appKey = "97771535";
        String appSecret = "4A3C10287D414583";
        String method = "nuonuo.ElectronInvoice.requestBillingNew"; // API方法名
        String token = info.getAccessToken();
        if (token == null) {
            //自用型应用获取令牌
            String json = NNOpenSDK.getIntance().getMerchantToken(appKey, appSecret);
            System.out.println("json" + json);
            org.json.JSONObject jSONObject = new org.json.JSONObject(json);
            token = jSONObject.get("access_token").toString();
            info.setAccessToken(token);
            tcInvoiceMapper.updateById(info);
        }
        BigDecimal amount = param.getAmount().divide(BigDecimal.valueOf(100), 2, BigDecimal.ROUND_HALF_DOWN);
        String address = param.getRegist_address();
        if (address == null) {
            address = "";
        }
        String bankAccount = param.getBank_account();
        if (bankAccount == null) {
            bankAccount = "";
        }
        BigDecimal taxRate=new BigDecimal("0.03");
        /**
         * 金额/（1+税率）* 税率
         */
        BigDecimal tax = amount.
                divide(new BigDecimal(1).add(taxRate),2,BigDecimal.ROUND_HALF_DOWN).
                multiply(taxRate).
                setScale(2,BigDecimal.ROUND_HALF_DOWN);
        BigDecimal excludeAmount = new BigDecimal(amount.doubleValue()-tax.doubleValue()).setScale(2,BigDecimal.ROUND_HALF_DOWN);
        String content = "{" +
                "\"order\": {" +
                "\"terminalNumber\": \"\"," +
                "\"invoiceDetail\": [ " +
                "{" +
                "\"specType\": \"\"," +
                "\"taxExcludedAmount\": \"" + excludeAmount + "\"," +
                "\"invoiceLineProperty\": \"0\"," +
                "\"favouredPolicyName\": \"\"," +
                "\"num\": \"1\"," +
                "\"withTaxFlag\": \"1\"," +
                "\"tax\": \""+tax+"\"," +
                "\"favouredPolicyFlag\": \"0\"," +
                "\"taxRate\": \""+taxRate+"\"," +
                "\"unit\": \"\"," +
                "\"deduction\": \"0\"," +
                "\"price\": \"" + amount + "\"," +
                "\"zeroRateFlag\": \"\"," +
                "\"goodsCode\": \"\"," +
                "\"selfCode\": \"\"," +
                "\"goodsName\": \"客运服务费\"," +
                "\"taxIncludedAmount\": \"" + amount + "\" " +
                "}" +
                "]," +
                "\"buyerTel\": \"" + param.getReceive_mobile() + "\"," +
                "\"listFlag\": \"0\"," + //清单标志：非清单:0；清单:1，默认:0
                "\"pushMode\": \"2\"," +
                "\"departmentId\": \"9F7E9439CA8B4C60A2FFF3EA3290B088\"," +
                "\"clerkId\": \"e8dd73c6afd24df49b407906bcfcd468\"," +//开票员ID
                "\"remark\": \"" + param.getInvoice_remark() + "\"," +
                "\"checker\": \"杜莉\"," +
                "\"payee\": \"杜莉\"," + //收款人
                "\"buyerAddress\": \"" + address + "\"," +
                "\"buyerTaxNum\": \"" + param.getTax_number() + "\"," +
                "\"invoiceType\": \"1\"," +
                "\"invoiceLine\": \"p\"," +
                "\"email\": \"" + param.getReceive_email() + "\"," +
                "\"salerAccount\": \"" + "7411910182600026305" + "中信银行股份有限公司成都红星路支行" + "\"," +
                "\"salerTel\": \"028-68881888\"," +
                "\"orderNo\": \"" + param.getOrder_id() + "\"," +
                //"\"callBackUrl\": \"http:127.0.0.1/invoice/callback/\"," +
                "\"buyerName\": \"" + param.getTitle() + "\"," +
                "\"invoiceDate\": \"" + sdf.format(date) + "\"," +
                "\"invoiceCode\": \"\"," +
                "\"invoiceNum\": \"\"," +
                "\"salerAddress\": \"成都市武侯区七里路499号1栋3层302号\"," +
                "\"clerk\": \"张玲\"," + //开票员
                "\"buyerPhone\": \"" + param.getReceive_mobile() + "\"," +
                "\"buyerAccount\": \"" + bankAccount + "\"," +
                "\"productOilFlag\": \"0\"," +
                "\"extensionNumber\": \"\"," +
                "\"salerTaxNum\": \"" + taxnum + "\"," +
                "\"listName\": \"详见销货清单\"," +
                "\"proxyInvoiceFlag\": \"0\" " +
                "} " +
                "}";

        String url = "https://sdk.nuonuo.com/open/v1/services"; // SDK请求地址
        String senid = UUID.randomUUID().toString().replace("-", ""); // 唯一标识，32位随机码，无需修改，保持默认即可
        String result = sdk.sendPostSyncRequest(url, senid, appKey, appSecret, token, taxnum, method, content);
        System.out.println(result);
        log.info("诺诺发票请求返回:{}",result);
        try {
            //转换获取发票序列号
            org.json.JSONObject jSONObject2 = new org.json.JSONObject(result);
            String result2 = jSONObject2.get("result").toString();
            org.json.JSONObject jSONObject3 = new org.json.JSONObject(result2);
            String invoiceSerialNum = jSONObject3.get("invoiceSerialNum").toString();
            return invoiceSerialNum;
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public TongChengRv getInvoiceStatus(TcInvoiceQueryParam param) {
        log.info("同城获取发票状态入参：{}", JSON.toJSONString(param));
        if (param.getInvoice_id() == null) {
            return TongChengRv.error(ETongChengErrorCode.invoiceid_null);
        }
        TcInvoiceInfo info = tcInvoiceMapper.selectById(param.getInvoice_id());
        if (info == null) {
            return TongChengRv.error(ETongChengErrorCode.order_is_null);
        }
        //获取诺诺令牌
        TcInvoiceInfo info2 = tcInvoiceMapper.selectById(1);
        if (info2 == null) {
            info2.setId(1L);
            tcInvoiceMapper.insert(info2);
        }
        NNOpenSDK sdk = NNOpenSDK.getIntance();
        String taxnum = "91510107749745776R"; // 授权企业税号
        String appKey = "97771535";
        String appSecret = "4A3C10287D414583";
        String token = info2.getAccessToken();
        if (token == null) {
            //自用型应用获取令牌
            String json = NNOpenSDK.getIntance().getMerchantToken(appKey, appSecret);
            System.out.println("json" + json);
            org.json.JSONObject jSONObject = new org.json.JSONObject(json);
            token = jSONObject.get("access_token").toString();

            info2.setAccessToken(token);
            tcInvoiceMapper.updateById(info2);
        }
        String method = "nuonuo.ElectronInvoice.queryInvoiceResult"; // API方法名
        String content = "{" +
                "\"isOfferInvoiceDetail\": \"1\"," +
                "\"orderNos\": []," +
                "\"serialNos\": [" +
                "\"" + info.getInvoiceSerialNum() + "\"" +
                "] " +
                "}";
        String url = "https://sdk.nuonuo.com/open/v1/services"; // SDK请求地址
        String senid = UUID.randomUUID().toString().replace("-", ""); // 唯一标识，32位随机码，无需修改，保持默认即可
        String result = sdk.sendPostSyncRequest(url, senid, appKey, appSecret, token, taxnum, method, content);
        System.out.println(result);
        try {
            org.json.JSONObject jSONObject2 = new org.json.JSONObject(result);
            String result2 = jSONObject2.get("result").toString();
            System.out.println("----->" + result2);
            org.json.JSONArray jSONOArray = new org.json.JSONArray(result2);
            System.out.println(jSONOArray);
            org.json.JSONObject jSONObject3 = (org.json.JSONObject) jSONOArray.get(0);

            String pdfUrl = jSONObject3.get("pdfUrl").toString();
            if (pdfUrl == null || pdfUrl == "") {
                return TongChengRv.error(ETongChengErrorCode.invoiceid_look_no_access);
            }
            //更新发票的信息
            info.setInvoiceUrl(pdfUrl);
            info.setInvoiceStatus(2);
            tcInvoiceMapper.updateById(info);
        } catch (Exception e) {
            return TongChengRv.error(ETongChengErrorCode.invoiceid_look_no_access);
        }

        //返回信息
        InvoiceResults results = new InvoiceResults();
        results.setInvoice_id(info.getId());
        results.setAmount(info.getAmount());
        results.setApplication_time(param.getTimestamp());
        results.setReceive_name(info.getReceiveName());
        results.setReceive_email(info.getReceiveEmail());
        results.setReceive_mobile(info.getReceiveMobile());
        results.setInvoice_type(info.getInvoiceType());
        results.setInvoice_url(info.getInvoiceUrl());
        results.setTitle(info.getTitle());
        results.setStatus(info.getInvoiceStatus());
        return TongChengRv.wrap2(results);
    }



    private Integer getRulesNo(String origin, String destination, String cityCode, int callType) {
        Integer stationKind = 0;
        Integer rulesNo = null;
        if(callType == 3 || callType ==4){
            stationKind = 1;
        }
        if(callType == 5 || callType ==6){
            stationKind = 2;
        }
        QueryWrapper<com.xnyzc.lhy.didi.entity.price.OaSysBillSpecialSceneRule> sceneRuleQueryWrapper = new QueryWrapper<>();
        sceneRuleQueryWrapper.eq(com.xnyzc.lhy.didi.entity.price.OaSysBillSpecialSceneRule.CITY_CODE,cityCode);
        sceneRuleQueryWrapper.eq(com.xnyzc.lhy.didi.entity.price.OaSysBillSpecialSceneRule.STATION_KIND,stationKind);
        List<com.xnyzc.lhy.didi.entity.price.OaSysBillSpecialSceneRule> specialSceneRules = oaSysBillSpecialSceneRuleMapper.selectList(sceneRuleQueryWrapper);
        if(CheckUtil.objIsNotEmpty(specialSceneRules)){
            for (OaSysBillSpecialSceneRule oaBillScene:specialSceneRules
            ) {
                String stationKeyword = oaBillScene.getStationKeyword();
                //如果是接机或接站 判断起点中是否包含keyword
                if((callType == 3 || callType == 5) && origin.contains(stationKeyword)){
                    rulesNo = oaBillScene.getRulesNo();
                }
                //如果是送机或送站 判断终点中是否包含keyword
                else  if((callType == 4 || callType == 6) && destination.contains(stationKeyword)){
                    rulesNo = oaBillScene.getRulesNo();
                }
            }
        }
        return rulesNo;
    }

    @Override
    public TongChengRv getTcDrivers(TcDriverParam driverParam) {
        log.info("同城获取附近司机入参：{}", JSON.toJSONString(driverParam));
        List<OaDVehicleGps> result = new ArrayList<>();
        HashMap<String, Point> map = new HashMap<>();

        Qw qw = Qw.create();
        qw.select(OaDUserInfo.DRIVER_ID);
        qw.eq(OaDUserInfo.ACCEPTANC_ORDER_STATUS, 1).eq(OaDUserInfo.IS_ORDER, 0);
        List<OaDUserInfo> list = userInfoMapper.selectList(qw);
        log.info("ORDER_HISTORY 同程接送机:查询到的未接单司机个数: {}", list.size());
        for (OaDUserInfo oaDUserInfo : list) {
            // 司机轨迹前缀 + 司机ID
            String str = redisCommon.getStr(RedisPrefixConstant.GPS_VEH_KEY_PREFIX + oaDUserInfo.getDriverId());

            //判断是否有在线车辆
            if (CheckUtil.strIsNotEmpty(str)) {
                //获取司机轨迹
                OaDVehicleGps gps = JSON.parseObject(str, OaDVehicleGps.class);
                if (CheckUtil.objIsEmpty(gps)) {
                    continue;
                }
                //如果经纬度为空退出本次循环
                if (CheckUtil.strIsEmpty(gps.getLng()) || CheckUtil.strIsEmpty(gps.getLat())) {
                    continue;
                }
                Point point = new Point(Double.valueOf(gps.getLng()), Double.valueOf(gps.getLat()));
                map.put(String.valueOf(gps.getDriverId()), point);
                result.add(gps);
            }
        }
        log.info("ORDER_HISTORY 同程接送机:获取到有轨迹并且未接单的司机个数: {}", result.size());

        int size = result.size();
        if (size > 0) {
            //利用Redis中的GEO功能获取范围内的所有司机
            String key = RedisPrefixConstant.DIRVER_GEO + IDUtil.nextId();
            redisCommon.addGeos(map, key);
            Map<String, Object> stringObjectMap = redisCommon.geoRadius(driverParam.getMax_distance(), driverParam.getLon(), driverParam.getLat(), key);
            if (stringObjectMap.containsKey("keys")) {
                List<String> keys = (ArrayList) stringObjectMap.get("keys");
                int ksize = keys.size();
                log.info("ORDER_HISTORY 同程接送机:开始找车,筛选出符合里程要求的司机个数: [{}]", ksize);
                if (ksize > 0) {
                    Random random = new Random();
                    int index = random.nextInt(ksize);
                    String driverId = keys.get(index);

                    OaDVehicleGps driverGps = null;
                    for (OaDVehicleGps gps : result) {
                        if (driverId.equals(gps.getDriverId().toString())) {
                            driverGps = gps;
                        }
                    }
                    if (driverGps == null) {
                        return TongChengRv.wrap();
                    }
                    TcAroundDriverResults results = new TcAroundDriverResults();
                    results.setLon(Double.valueOf(driverGps.getLng()));
                    results.setLat(Double.valueOf(driverGps.getLat()));
                    int distance = (int) Math.ceil(driverGps.getDistance());
                    results.setDistance(distance);
                    int speed = Integer.valueOf(driverGps.getSpeed());
                    int duration = distance / speed;
                    results.setDuration(duration);
                    results.setBearing(0D);

                    return TongChengRv.wrap(results);
                }
            }
        }
        return TongChengRv.wrap();
    }


}
